#ifndef SYLAR_CONFIG_H
#define SYLAR_CONFIG_H
#include "thread.h"
#include <memory>
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <functional>
#include <set>
#include "yaml-cpp/yaml.h" // 移除原log.h依赖（若仅日志使用）

#include <stdint.h>

#include "thread.h"  // 显式包含 RWMutex 的定义
namespace sylar
{
    class ConfigVarBase
    {
    public:
        typedef std::shared_ptr<ConfigVarBase> ptr;
        ConfigVarBase(const std::string &name, const std::string &description = "") : m_name(name), m_description(description)
        {
            std::transform(m_name.begin(), m_name.end(), m_name.begin(), ::tolower);
        }
        virtual ~ConfigVarBase() {}
        virtual std::string toString() = 0;
        const std::string &getDescription() const
        {
            return m_description;
        }
        const std::string &getName() const { return m_name; }

        virtual bool fromString(const std::string &val) = 0;

        virtual std::string getTypeName() const = 0;

    protected:
        std::string m_name;
        std::string m_description;
    };

    template <class F, class T>
    class LexicalCast
    {
    public:
        T operator()(const F &from)
        {
            return boost::lexical_cast<T>(from);
        }
    };

    // vector<T> 转换：修复循环变量类型 + emplace_back优化
    template <class T>
    class LexicalCast<std::string, std::vector<T>>
    {
    public:
        std::vector<T> operator()(const std::string &str)
        {
            YAML::Node node = YAML::Load(str);
            std::vector<T> vec;
            std::stringstream ss;
            LexicalCast<std::string, T> handler;
            // 修复：用size_t替代std::vector<int>::size_type（避免类型绑定错误）
            for (size_t i = 0; i < node.size(); ++i)
            {
                ss.str("");
                ss << node[i];
                vec.emplace_back(handler(ss.str())); // 优化：emplace_back直接构造
            }
            return vec;
        }
    };

    template <class T>
    class LexicalCast<std::vector<T>, std::string>
    {
    public:
        std::string operator()(const std::vector<T> &vec)
        {
            std::stringstream ss;
            YAML::Node node;
            // 修复：用size_t替代std::vector<int>::size_type
            LexicalCast<T, std::string> handler;
            for (size_t i = 0; i < vec.size(); ++i)
            {
                node.push_back(YAML::Load(handler(vec[i])));
            }
            ss << node;
            return ss.str();
        }
    };

    // list<T> 转换：修复循环变量类型 + emplace_back优化
    template <class T>
    class LexicalCast<std::string, std::list<T>>
    {
    public:
        std::list<T> operator()(const std::string &str)
        {
            YAML::Node node = YAML::Load(str);
            std::list<T> vec;
            std::stringstream ss;
            LexicalCast<std::string, T> handler;
            // 修复：用size_t替代std::vector<int>::size_type
            for (size_t i = 0; i < node.size(); ++i)
            {
                ss.str("");
                ss << node[i];
                vec.emplace_back(handler(ss.str())); // 优化：emplace_back直接构造
            }
            return vec;
        }
    };

    template <class T>
    class LexicalCast<std::list<T>, std::string>
    {
    public:
        std::string operator()(const std::list<T> &vec)
        {
            std::stringstream ss;
            YAML::Node node;
            LexicalCast<T, std::string> handler;
            for (auto &tmp : vec)
            {
                node.push_back(YAML::Load(handler(tmp)));
            }
            ss << node;
            return ss.str();
        }
    };

    // set<T> 转换：修复循环变量类型 + emplace优化 + force_insert错误修复
    template <class T>
    class LexicalCast<std::string, std::set<T>>
    {
    public:
        std::set<T> operator()(const std::string &str)
        {
            YAML::Node node = YAML::Load(str);
            std::set<T> vec;
            std::stringstream ss;
            LexicalCast<std::string, T> handler;
            // 修复：用size_t替代std::vector<int>::size_type
            for (size_t i = 0; i < node.size(); ++i)
            {
                ss.str("");
                ss << node[i];
                vec.emplace(handler(ss.str())); // 优化：emplace直接构造
            }
            return vec;
        }
    };

    template <class T>
    class LexicalCast<std::set<T>, std::string>
    {
    public:
        std::string operator()(const std::set<T> &vec)
        {
            std::stringstream ss;
            YAML::Node node;
            LexicalCast<T, std::string> handler;
            for (auto &tmp : vec)
            {
                // 修复：force_insert是map方法，序列用push_back
                node.push_back(YAML::Load(handler(tmp)));
            }
            ss << node;
            return ss.str();
        }
    };

    // unordered_set<T> 转换：修复循环变量类型 + emplace优化
    template <class T>
    class LexicalCast<std::string, std::unordered_set<T>>
    {
    public:
        std::unordered_set<T> operator()(const std::string &str)
        {
            YAML::Node node = YAML::Load(str);
            std::unordered_set<T> vec;
            std::stringstream ss;
            LexicalCast<std::string, T> handler;
            // 修复：用size_t替代std::vector<int>::size_type
            for (size_t i = 0; i < node.size(); ++i)
            {
                ss.str("");
                ss << node[i];
                vec.emplace(handler(ss.str())); // 优化：emplace直接构造
            }
            return vec;
        }
    };

    template <class T>
    class LexicalCast<std::unordered_set<T>, std::string>
    {
    public:
        std::string operator()(const std::unordered_set<T> &vec)
        {
            std::stringstream ss;
            YAML::Node node;
            LexicalCast<T, std::string> handler;
            for (auto &tmp : vec)
            {
                node.push_back(YAML::Load(handler(tmp)));
            }
            ss << node;
            return ss.str();
        }
    };

    // map<string, T> 转换：emplace优化（移除std::make_pair）
    template <class T>
    class LexicalCast<std::string, std::map<std::string, T>>
    {
    public:
        std::map<std::string, T> operator()(const std::string &str)
        {
            YAML::Node node = YAML::Load(str);
            std::map<std::string, T> vec;
            std::stringstream ss;
            LexicalCast<std::string, T> handler;
            for (auto it = node.begin(); it != node.end(); ++it)
            {
                ss.str("");
                ss << it->second;
                // 优化：直接传参数，emplace自动构造键值对（无需std::make_pair）
                vec.emplace(it->first.Scalar(), handler(ss.str()));
            }
            return vec;
        }
    };

    template <class T>
    class LexicalCast<std::map<std::string, T>, std::string>
    {
    public:
        std::string operator()(const std::map<std::string, T> &vec)
        {
            std::stringstream ss;
            YAML::Node node;
            LexicalCast<T, std::string> handler;
            for (auto it = vec.begin(); it != vec.end(); ++it)
            {
                node[it->first] = YAML::Load(handler(it->second));
            }
            ss << node;
            return ss.str();
        }
    };

    // unordered_map<string, T> 转换：emplace优化（移除std::make_pair）
    template <class T>
    class LexicalCast<std::string, std::unordered_map<std::string, T>>
    {
    public:
        std::unordered_map<std::string, T> operator()(const std::string &str)
        {
            YAML::Node node = YAML::Load(str);
            std::unordered_map<std::string, T> vec;
            std::stringstream ss;
            LexicalCast<std::string, T> handler;
            for (auto it = node.begin(); it != node.end(); ++it)
            {
                ss.str("");
                ss << it->second;
                // 优化：直接传参数，emplace自动构造键值对（无需std::make_pair）
                vec.emplace(it->first.Scalar(), handler(ss.str()));
            }
            return vec;
        }
    };

    template <class T>
    class LexicalCast<std::unordered_map<std::string, T>, std::string>
    {
    public:
        std::string operator()(const std::unordered_map<std::string, T> &vec)
        {
            std::stringstream ss;
            YAML::Node node;
            LexicalCast<T, std::string> handler;
            for (auto it = vec.begin(); it != vec.end(); ++it)
            {
                node[it->first] = YAML::Load(handler(it->second));
            }
            ss << node;
            return ss.str();
        }
    };

    template <class T, class FromStr = LexicalCast<std::string, T>, class ToStr = LexicalCast<T, std::string>>
    class ConfigVar : public ConfigVarBase
    {
    public:
    using RWMutexType = RWMutex;
        typedef std::shared_ptr<ConfigVar> ptr;
        typedef std::function<void(const T &old_val, const T &new_val)> on_change_cb;
        ConfigVar(const std::string &name, const T &default_value, const std::string &description) : ConfigVarBase(name, description), m_val(default_value)
        {
        }

        std::string toString() override
        {
            try
            {
                RWMutexType::ReadLock rlock(m_mutex);
                return ToStr()(m_val);
            }
            catch (std::exception &e)
            {
                std::cerr << "ConfigVar::toString exception " << e.what() << " convert: " << typeid(m_val).name() << " to string" << std::endl;
            }
            return "";
        }
        bool fromString(const std::string &val) override
        {
            try
            {
                setValue(FromStr()(val));
                return true;
            }
            catch (std::exception &e)
            {
                std::cerr << "ConfigVar::fromString exception " << e.what() << " convert: string to " << typeid(m_val).name() << std::endl;
            }
            return false;
        }
        const T &getValue() const
        {
            RWMutexType::ReadLock rlock(m_mutex);
            return m_val;
        }
        void setValue(const T &other_val)
        {
            {
                RWMutexType::ReadLock rlock(m_mutex);
                if (m_val == other_val)
                    return;
                for (auto &i : m_cbs)
                {
                    i.second(m_val, other_val);
                }
            }
            
            RWMutexType::WriteLock wlock(m_mutex);
            m_val = other_val;
        }
        std::string getTypeName() const override
        {
            return typeid(T).name();
        }
        uint64_t addListener(on_change_cb cb)
        {
            static uint64_t s_fun_id = 0;
            RWMutexType::WriteLock wlock(m_mutex);
            ++s_fun_id;
            m_cbs[s_fun_id] = cb;
            return s_fun_id;
        }
        void delListener(uint64_t id)
        {
            RWMutexType::WriteLock wlock(m_mutex);
            m_cbs.erase(id);
        }
        on_change_cb getListener(uint64_t id)
        {
            
            RWMutexType::ReadLock rlock(m_mutex);
            auto tmp = m_cbs.find(id);
            return tmp == m_cbs.end() ? nullptr : tmp->second;
        }
        void clearListener()
        {
            
            RWMutexType::WriteLock wlock(m_mutex);
            m_cbs.clear();
        }
        void clearListener(uint64_t id)
        {
            auto it = m_cbs.find(id);
            if (it != m_cbs.end())
            {

                uint64_t tmp_id = id;
                on_change_cb tmp_func = it->second;
                m_cbs.clear();
                m_cbs[tmp_id] = tmp_func;
            }
        }

    private:
        mutable RWMutexType m_mutex;
        T m_val;
        std::map<uint64_t, on_change_cb> m_cbs;
    };

    class Config
    {
    public:

    
    using RWMutexType = RWMutex;

        typedef std::map<std::string, ConfigVarBase::ptr> ConfigVarMap;
        typedef std::shared_ptr<Config> ptr;

        template <class T>
        static typename ConfigVar<T>::ptr Lookup(const std::string &name)
        {
            RWMutexType::ReadLock rlock(GetMutex());

            auto it = GetDatas().find(name);
            if (it == GetDatas().end())
            {
                return nullptr;
            }
            return std::dynamic_pointer_cast<ConfigVar<T>>(it->second);
        }

        template <class T>
        static typename ConfigVar<T>::ptr Lookup(const std::string &name, const T &default_value, const std::string &descrition)
        {
            
            RWMutexType::WriteLock wlock(GetMutex());
            auto may_fatal_it = GetDatas().find(name);
            if (may_fatal_it != GetDatas().end())
            {
                auto tmp2 = std::dynamic_pointer_cast<ConfigVar<T>>(may_fatal_it->second);
                if (tmp2 == nullptr)
                {
                    std::cerr << "Lookup name = " << name << " exists but error type: " << may_fatal_it->second->getTypeName()
                              << " the right type is " << typeid(T).name() << " val : " << may_fatal_it->second->toString() << std::endl;
                    return nullptr;
                }
                else
                {
                    std::cout << "Lookup name = " << name << " exists" << std::endl;
                    return tmp2;
                }
            }
            auto tmp = Lookup<T>(name);
            if (tmp)
            {
                std::cout << "Lookup name = " << name << " exists" << std::endl;
                return tmp;
            }
            if (name.find_first_not_of("abcdefghijklmnopqrstuvwxyz._0123456789") != std::string::npos)
            {
                std::cerr << "Config::lookUp() Lookup name invalid: " << name << std::endl;
                throw std::invalid_argument(name);
            }
            typename ConfigVar<T>::ptr v(new ConfigVar<T>(name, default_value, descrition));
            std::string cp_name = name;
            GetDatas()[cp_name] = v;
            return v;
        }
        static ConfigVarBase::ptr LookupBase(std::string &name);

        static void LoadFromYaml(const YAML::Node &root);

        static void Visit(std::function<void (ConfigVarBase::ptr)> cb);
    private:
        static ConfigVarMap &GetDatas()
        {

            static ConfigVarMap s_datas;
            return s_datas;
        }
        static RWMutexType& GetMutex()
        {
            static RWMutexType s_mutex;
            return s_mutex;
        }
    };

}

#endif